#! /bin/sh
# 
# Laptop mode tools module, called from /usr/sbin/laptop_mode.
# Configuration in /etc/laptop-mode/conf.d/wireless-iwl-power.conf.
#
# PURPOSE: power saving for the Intel 3945 and 4965 adapters when using the
#          iwlwifi drivers.
#
# This script relies upon the name of the driver.
#

#
# Find all the wireless devices using the supplied driver names.
# Place the interface names on the list WIFI_IFNAMES.
#
findWifiIfsByDriver () {
	local DEVICE;
	local LINK_TARGET;
	local ENABLED;

	for DEVICE in /sys/class/net/*; do
		if [ -d $DEVICE/wireless -a -h $DEVICE/device/driver ]; then
			# See if the driver for $DEVICE matches the supplied one by checking the link to
			# the driver.
			LINK_TARGET=`readlink $DEVICE/device/driver`
			LINK_TARGET=${LINK_TARGET##*/}
			ENABLED=`cat $DEVICE/device/enable` 
			
			if [ $ENABLED -eq 1 -a "$LINK_TARGET" = "$1" ] ; then
				# add the interface name to the list
				WIFI_IFNAMES="$WIFI_IFNAMES ${DEVICE##*/}"
                        else
                                log "VERBOSE" "$DEVICE doesn't seem to be enabled. Radio Switched off?";
			fi
                else
                        # LP: #369113
                        # Kernel's 2.6.29 and above have been reported to be missing
                        # the $DEVICE/wireless folder.
                        dev=`basename $DEVICE`

			# Inverting return values, we get "0" for wireless device, 
			# and "1" for non-wireless device.
			($IWCONFIG $IFNAME 2>&1 | grep -q "no wireless extensions.") && ret=1 || ret=0
                        if [ "$ret" = "0" ]; then
			        # add the interface name to the list
		    		WIFI_IFNAMES="$WIFI_IFNAMES ${DEVICE##*/}"
                        fi
		fi
	done
}

if [ x$CONTROL_IWL_POWER = x1 ] || [ x$ENABLE_AUTO_MODULES = x1 -a x$CONTROL_IWL_POWER = xauto ]; then
	log "VERBOSE" "Setting power levels for iwlwifi wireless interfaces."

	# Provide defaults for config file settings
	[ "$IWL_AC_POWER" ]   || IWL_AC_POWER=0
	[ "$IWL_BATT_POWER" ] || IWL_BATT_POWER=3

	# find executables
	if [ -x /sbin/iwpriv ] ; then
		IWPRIV=/sbin/iwpriv
	elif [ -x /usr/sbin/iwpriv ] ; then
		IWPRIV=/usr/sbin/iwpriv
	else
		log "VERBOSE" "iwpriv is not installed"
	fi
	if [ -x /sbin/iwconfig ] ; then
		IWCONFIG=/sbin/iwconfig
	elif [ -x /usr/sbin/iwconfig ] ; then
		IWCONFIG=/usr/sbin/iwconfig
	else
		log "VERBOSE" "iwconfig is not installed"
	fi

	WIFI_IFNAMES=""
	[ -d /sys/module/iwl3945 ] && findWifiIfsByDriver iwl3945
	[ -d /sys/module/iwl4965 ] && findWifiIfsByDriver iwl4965
	[ -d /sys/module/iwlagn ] && findWifiIfsByDriver iwlagn
	for IF in $WIFI_IFNAMES ; do
		if [ $ON_AC -eq 1 ] ; then
			log "VERBOSE" "On AC power: setting power level for $IF to $IWL_AC_POWER."
			if [ -f /sys/class/net/$IF/device/power_level ]; then
				echo $IWL_AC_POWER > /sys/class/net/$IF/device/power_level;
				log "VERBOSE" "Using method echo for power mgmt"
			else
				# For iwlagn, it is one standard behavior. Not multiple like ipwXXXX
				# Thus let's just simply exec the command here.
				$IWCONFIG $IF power off
				log "VERBOSE" "Using $IWCONFIG for power mgmt"
			fi
		else
			log "VERBOSE" "On battery: setting power level for $IF to $IWL_BATT_POWER."
			if [ -f /sys/class/net/$IF/device/power_level ]; then
				echo $IWL_BATT_POWER > /sys/class/net/$IF/device/power_level;
				log "VERBOSE" "Using method echo for power mgmt"
			else
				$IWCONFIG $IF power on
				log "VERBOSE" "Using $IWCONFIG for power mgmt"
			fi
		fi
	done
else
	log "VERBOSE" "Intel IWL Wireless power setting is disabled."
fi

